﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//内存函数
/*
在缓冲区之间复制字节
void *memcpy(
void *dest,              //新缓存区
const void *src,        //源缓存区
size_t count );         //复制大小
*/
//int main()
//{
//	int dest[6] = { 1,2,3,4 };
//	int src[] = { 'h','i','\0','i','\0' };
//
//	memcpy(dest, src, sizeof(src));
//	for (size_t i = 0; i < 6; i++)
//	{
//		printf("%d ", dest[i]);
//	}
//	return 0;
//}

//模拟实现memcpy
//void* my_memcpy(void* dest, const void* src, size_t count)
//{
//	void* ret = dest;//接收新缓存区
//	assert(dest);
//	assert(src);
//
//	while (count--)
//	{
//		*(char*)dest = *(char*)src;//按照一字节一字节复制 没有遗漏
//		(char*)dest = (char*)dest + 1;//dest指针后移
//		(char*)src = (char*)src + 1;//src指针后移
//	}
//	return ret;
//}

/*
 将一个缓冲区移到另一个缓冲区
void *memmove(
   void *dest,
   const void *src,
   size_t count
);
*/

//int main()
//{
//	int dest[6] = { 1,2,3,4 };
//	int src[] = { 'h','i','\0','i','\0' };
//
//	memmove(dest + 1, src + 2, sizeof(src));
//	for (size_t i = 0; i < 6; i++)
//	{
//		printf("%d ", dest[i]);
//	}
//	return 0;
//}

//int main(void)
//{
//	char buffer[] = "This is a test of the memset function";
//
//	printf("Before: %s\n", buffer);
//	/*memset(buffer + 4, '*', 4);*/
//	//清空缓存区
//	memset(buffer, '\0', sizeof(buffer));
//	printf("After:  %s\n", buffer);
//}
/************************************************分界线*******************************************************/

//动态内存管理
//malloc free
// void* malloc (size_t size);
//int main()
//{
//	//创建固定数组 分配在栈区
//	int arr1[5] = { 0,1,2,3,4 };
//	for (size_t i = 0; i < sizeof(arr1) / sizeof(int); i++)
//	{
//		printf("%d ", arr1[i]);
//	}
//	//定义一个可变数组 分配在堆区
//	int* arr2 = (int*)malloc(5 * sizeof(int));
//	//一定要进行检查！！！！！！！
//	if (arr2 == NULL)
//	{
//		perror("error managing !");
//		return 1;
//	}
//	printf("\n");
//	for (size_t i = 0; i < 5; i++)
//	{
//		arr2[i] = i + 10;//初始化
//		printf("%zd ", *(arr2) + (i*10));
//	}
//	//别忘了手动释放和将指针置为NULL
//	free(arr2);
//	arr2 = NULL;
//	return 0;
//}

/*
void *realloc(
void *memblock,                                                //指向先前的已经分配了内存的指针
size_t size );                                                 //新内存大小，单位字节
*/
//模拟三部门预算增加至五部门
//void Print(double* arr, size_t size);
//
//int main()
//{
//	size_t size = 3;//三部门
//	double* budget = (double*)malloc(size * sizeof(double));//创建三部门
//	if (budget == NULL)//检查错误
//	{
//		perror("error managing old_budget!");
//		return 1;
//	}
//	puts("before:");
//	budget[0] = 111;
//	budget[1] = 222;
//	budget[2] = 333;//输入三部门的数据情况
//
//	Print(budget, size);//输出三部门数据
//
//	size_t new_size = 5;//部门数更新
//	double* new_budget = (double*)realloc(budget, new_size * sizeof(double));//创建新的缓存区增加部门数
//	if (new_budget == NULL)
//	{
//		perror("error managing new_budget!");
//		free(budget);//新内存没创建成功 释放旧的即可
//		return 1;
//	}
//
//	puts("\nafter:");
//	budget = new_budget;//更新指针
//	budget[3] = 444;
//	budget[4] = 555;
//	Print(budget, new_size);//更新数据并输出
//
//	free(budget);//更新指针时新旧内存已经一样了 释放一个即可
//	budget = NULL;
//	new_budget = NULL;
//
//	return 0;
//}
//void Print(double* arr, size_t size)
//{
//	for (size_t i = 0; i < size; i++)
//	{
//		printf("%.2f ", arr[i]);
//	}
//}

/*
void *calloc(
size_t number,                //元素数量
size_t size );				  //一个元素的大小 单位字节
使用初始化为 0 的元素分配内存
*/

//int main()
//{
//	int* arr = (int*)calloc(10, sizeof(int));
//	if (arr == NULL)
//	{
//		perror("error!");
//		free(arr);
//		return 1;
//	}
//	for (size_t i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	free(arr);
//	arr = NULL;
//	return 0;
//}

//
//void GetMemory(char* p)
//{
//	p = (char*)malloc(100);
//}
//void Test(void)
//
//{
//	char* str = NULL;
//	GetMemory(str);//对空指针解引用  值传递 没有接收到地址
//	strcpy(str, "hello world");
//	printf(str);
//	//没有释放内存空间
//}
//int main()
//{
//	Test();
//	return 0;
//}

//返回栈空间地址
//char* GetMemory(void)
//{
//	char p[] = "hello world";
//	return p;
//}
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();
//	printf(str);
//}
// 
// 不够完美 没有释放内存和检查内存是否开辟成功
//void GetMemory(char** p, int num)
//{
//	*p = (char*)malloc(num);
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str, 100);
//	strcpy(str, "hello");
//	printf(str);
//}
//int main()
//{
//	Test();
//	return 0;
//}

//柔性数组
//结构体中最后一个元素是数组且数组元素个数未知
//
//typedef struct st_type
//{
//	char name[20];
//	double height;
//	int arr[];//柔性数组成员
//}a_type;

/*
柔性数组的特点：
结构中的柔性数组成员前⾯必须⾄少⼀个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存。
包含柔性数组成员的结构⽤malloc()函数进⾏内存的动态分配，并且分配的内存应该大于结构的大
小，以适应柔性数组的预期大小。
*/

//typedef struct st_type
//{
//	int i;
//	int a[0];//柔性数组成员
//
//}type_a;
//int main()
//{
//	printf("%zd\n", sizeof(type_a));//输出的是4
//	return 0;
//}
//
// 

//typedef struct St
//{
//	char c;
//	double d;
//	int arr[];
//}St;

//int main()
//{
//	St* ps = (St *)malloc(sizeof(St) + 10 * sizeof(int));
//	if (ps == NULL)
//	{
//		perror("error managing ps!");
//		free(ps);
//		ps = NULL;
//		return 1;
//	}
//	//业务处理
//	ps->c = 'a';
//	ps->d = 3.14;
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		ps->arr[i] = i ;
//	}
//	//扩大数组
//	St* ptr = (St*)realloc(ps, sizeof(St) + 15 * sizeof(int));
//	if (ptr == NULL)
//	{
//		perror("error managing ptr!");
//		return 1;
//	}
//	else ps = ptr;
//	for (int i = 10; i < 15; i++)
//	{
//		ps->arr[i] = i ;
//	}
//	for (int i = 0; i < 15; i++)
//	{
//		printf("%d ", ps->arr[i]);
//	}
//	printf("\n%c\n%.2f",ps -> c,ps -> d);
//
//	free(ps);
//	ps = NULL;
//	return 0;
//}

typedef struct St
{
	char c;
	double d;
	int* arr;
}St;

int main()
{
	St* ps = (St*)malloc(sizeof(St));
	if (ps == NULL)
	{
		perror("malloc");
		free(ps);
		ps = NULL;
		return 1;
	}
	ps->c = 'a';
	ps->d = 3.14;

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		perror("malloc-2");
		free(ps -> arr);
		ps->arr = NULL;
	}
	for (size_t i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	//扩大数组
	int* ptr = (int*)realloc(ps->arr, 15 * sizeof(int));
	if (ptr == NULL)
	{
		perror("realloc");
		free(ptr);
		ptr = NULL;
		return 1;
	}
	else ps->arr = ptr;
	for (size_t i = 10; i < 15; i++)
	{
		ps->arr[i] = i;
	}
	for (size_t i = 0; i < 15; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n%c\n%.2f", ps->c, ps->d);

	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;

	return 0;
}